package com.zis.platform.common.authentication;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.zis.util.MD5Salt;
import com.zis.platform.common.util.CacheCoreUtil;
import com.zis.platform.core.entity.DataAuthUserEntity;
import com.zis.platform.core.entity.GroupEntity;
import com.zis.platform.core.entity.RoleEntity;
import com.zis.platform.core.entity.SysEntity;
import com.zis.platform.core.entity.UserEntity;
import com.zis.platform.core.service.DataAuthGroupService;
import com.zis.platform.core.service.DataAuthRoleService;
import com.zis.platform.core.service.DataAuthUserService;
import com.zis.platform.core.service.GroupService;
import com.zis.platform.core.service.ResService;
import com.zis.platform.core.service.UserService;

/**
 * <b>说明：</b> Apache Shiro 鉴权
 * 
 * @ClassName: CoreAuthorizingRealm
 * @author zhaohaitao(2543)
 * @date 2015-7-9 下午6:12:51
 * 
 */
public class CoreAuthorizingRealm extends AuthorizingRealm
{
    @Autowired
    private UserService userService;
    
    @Autowired
    private ResService resService;
    
    @Autowired
    private GroupService groupService;
    
    @Autowired
    public DataAuthUserService dataAuthService;
    
    @Autowired
    private DataAuthRoleService dataAuthRoleService;
    
    @Autowired
    private DataAuthGroupService dataAuthGroupService;
    
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
        throws AuthenticationException
    {
        // 根据用户配置用户与权限
        UserToken token = (UserToken)authcToken;
        UserEntity user = userService.findByLoginName(token.getUsername());
        // 密码校验
        if (user != null)
        {
            token.setUser(user);
            if (!user.isEnable())
            {
                throw new DisabledAccountException();
            }
            if (user.isLocked())
            {
                throw new LockedAccountException();
            }
            boolean compare = MD5Salt.compare(new String(token.getPassword()), user.getSalt(), user.getPassword());
            if (!compare)
            {
                throw new IncorrectCredentialsException();
            }
            else
            {
                String userId = user.getUserId();
                if (user.isSupperManager())
                {
                    try
                    {
                        token.setMenus(resService.findAll());
                        List<SysEntity> sysInfos = CacheCoreUtil.getSysInfos();
                        for (SysEntity sys : sysInfos)
                        {
                            token.getSysIds().add(sys.getSysId());
                        }
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
                else
                {
                    // ################################################# 获取资源权限
                    Map<String, List<DataAuthUserEntity>> dataPers = new HashMap<String, List<DataAuthUserEntity>>();
                    // 获取用户角色信息
                    List<RoleEntity> roles = userService.findRolesByUserId(userId);
                    GroupEntity userGroup = groupService.findGroupAndResByGroupId(user.getGroup().getGroupId());
                    token.setRolesAndUserGroup(userGroup, roles);
                    HttpServletRequest request =
                        ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
                    SysEntity sysInfo = CacheCoreUtil.getSysInfo(request);
                    if (!token.getSysIds().contains(sysInfo.getSysId()))
                    {
                        throw new AccountException("您没有当前系统的管理权限。");
                    }
                    // ################################################# 获取数据权限
                    // 根据用户所拥有的角色信息获取 角色数据权限
                    for (RoleEntity r : roles)
                    {
                        dataPers.putAll(dataAuthRoleService.findByRoleId(r.getRoleId(), user));
                    }
                    // 根据用户所属用户组获取 用户组数据权限
                    dataPers.putAll(dataAuthGroupService.findByGroupId(user));
                    dataPers.putAll(dataAuthService.findByUserId(userId));
                    if (CollectionUtils.isEmpty(token.getSysMenus()))
                    {
                        throw new AccountException("您还没有访问该系统的权限。");
                    }
                    token.setDataPermission(dataPers);
                }
                userService.updateUserLoginInfo(token.getUser().getUserId(), token.getHost(), token.getUser()
                    .getLastLoginMac());
                return new SimpleAuthenticationInfo(token, token.getPassword(), user.getSalt());
            }
        }
        else
        {
            throw new UnknownAccountException("用户名错误，请重试。");
        }
    }
    
    /**
     * 权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
    {
        UserToken loginUser = (UserToken)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();
        if (!loginUser.getUser().isSupperManager())
        {
            List<RoleEntity> roles = loginUser.getRoles();
            Set<String> permissionSet = new HashSet<String>();
            Set<String> roleSet = new HashSet<String>();
            for (RoleEntity role : roles)
            {
                roleSet.add(role.getRoleName());
                permissionSet.addAll(role.getResourcesStr());
            }
            if (!CollectionUtils.isEmpty(permissionSet))
            {
                auth.addRoles(roleSet);
                auth.addStringPermissions(permissionSet);
            }
        }
        else
        {
            // 超级管理员 始终拥有所有权限
            auth.addStringPermission("*");
            return auth;
        }
        return auth;
    }
    
}
